package cn.pconline.officialclub.service;

import cn.pconline.autoclub.entity.Activity;
import cn.pconline.autoclub.service.ClubService;
import cn.pconline.autoclub.util.DateUtils;
import cn.pconline.autoclub.util.Pager;
import cn.pconline.autoclub.util.Result;
import cn.pconline.officialclub.entity.OActivity;
import cn.pconline.officialclub.entity.OActivityContent;
import cn.pconline.officialclub.entity.OActivityMember;
import cn.pconline.officialclub.entity.OClub;
import cn.pconline.officialclub.entity.OClubMember;
import java.util.ArrayList;
import java.util.List;
import org.gelivable.dao.SqlBuilder;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 官方车友会活动相关
 *
 * @author <a href="mailto:chensy0203@163.com">chensy</a>
 */
public class OActivityService extends ServiceKit {

    @Autowired
    private ClubService clubService;

    /**
     * 活动创建
     *
     * @param activity
     */
    public void createActivity(OActivity activity) {
        int longMessage = 0;
        String message = activity.getContent();
        if (message.length() > 255) {
            longMessage = 1;
            activity.setContent(message.substring(0, 255));
        }
        activity.setLongContent(longMessage);
        geliDao.create(activity);
        if (longMessage == 1) {
            createActivityContent(activity.getActivityId(), message);
        }
    }

    /**
     * 活动修改
     *
     * @param activity
     */
    public void updateActivity(OActivity activity) {
        int longMessage = 0;
        String message = activity.getContent();
        int oldLongMessage = activity.getLongContent();
        if (message.length() > 255) {
            longMessage = 1;
            activity.setContent(message.substring(0, 255));
        }
        activity.setLongContent(longMessage);
        geliDao.update(activity);
        if (oldLongMessage > 0) {
            //删除旧的超长内容
            SqlBuilder sql = new SqlBuilder();
            sql.appendSql(" delete from ").appendSql(getTableName(OActivityContent.class, activity.getActivityId()));
            sql.appendSql(" where activity_id = ").appendValue(activity.getActivityId());
            update(sql);
        }
        if (longMessage == 1) {
            createActivityContent(activity.getActivityId(), message);
        }
    }

    /**
     * 内容截断分批插入数据库
     *
     * @param activityId
     * @param message
     */
    private void createActivityContent(long activityId, String message) {
        if (message.length() < 255) {
            return;
        }
        StringBuilder sql = new StringBuilder();
        sql.append("insert into  ");
        sql.append(getTableName(OActivityContent.class, activityId));
        sql.append(" (content_id, activity_id, seq, content) value (?, ?, ?, ?)");
        //批量插入
        List<Object[]> batch = new ArrayList<Object[]>();
        for (int i = 255, n = 1, length = message.length(); i < length; i += 255, n++) {
            int j = Math.min(length, i + 255);
            Object[] values = new Object[]{geliDao.generateId(OActivityContent.class), activityId, n, message.substring(i, j)};
            batch.add(values);
        }
        jdbcTemplate.batchUpdate(sql.toString(), batch);
    }

    /**
     * 根据活动ID获取完整活动内容
     *
     * @param activityId
     * @return
     */
    public String getActivityContent(long activityId) {
        if (activityId < 1) {
            return null;
        }
        StringBuilder content = new StringBuilder("");
        OActivity activity = findById(OActivity.class, activityId);
        if (activity != null) {
            content.append(activity.getContent());
            if (activity.getLongContent() > 0) {
                SqlBuilder sql = new SqlBuilder();
                sql.appendSql(" select content_id from ").appendSql(getTableName(OActivityContent.class, activityId));
                sql.appendSql(" where activity_id = ").appendValue(activityId);
                sql.appendSql(" order by seq ");
                List<OActivityContent> listTxt = list(OActivityContent.class, activityId, sql);
                if (listTxt != null && !listTxt.isEmpty()) {
                    for (OActivityContent ctxt : listTxt) {
                        content.append(ctxt.getContent());
                    }
                }
            }
        }
        return content.toString();
    }
    /**
     * 根据活动ID获取活动内容(查前N条)
     *
     * @param activityId
     * @return
     */
    public String getActivityContent(long activityId,int limit) {
        if (activityId < 1) {
            return null;
        }
        StringBuilder content = new StringBuilder("");
        OActivity activity = findById(OActivity.class, activityId);
        if (activity != null) {
            content.append(activity.getContent());
            if (activity.getLongContent() > 0) {
                SqlBuilder sql = new SqlBuilder();
                sql.appendSql(" select content_id from ").appendSql(getTableName(OActivityContent.class, activityId));
                sql.appendSql(" where activity_id = ").appendValue(activityId);
                sql.appendSql(" order by seq ");
                List<OActivityContent> listTxt = listLimit(OActivityContent.class, activityId, sql,limit);
                if (listTxt != null && !listTxt.isEmpty()) {
                    for (OActivityContent ctxt : listTxt) {
                        content.append(ctxt.getContent());
                    }
                }
            }
        }
        return content.toString();
    }
    /**
     * 活动列表
     *
     * @param userId 用来判断活动状态
     * @param oClubId
     * @param pageNo
     * @param pageSize
     * @return
     */
    public Pager<OActivity> pageActivityBy(long userId, long oClubId, boolean isStart, int pageNo, int pageSize) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql(" select activity_id from ").appendSql(getTableName(OActivity.class));
        if (oClubId > 0) {
            sql.appendSql(" where o_club_id =").appendValue(oClubId);
        }
        if (isStart) {
            sql.appendSql(" and begin_date >= ").appendValue(DateUtils.getNow());
        }
        sql.appendSql(" and status = ").appendValue(OActivity.STATUS_YES);
        sql.appendSql(" order by create_at desc");
        Pager<OActivity> pager = pagerService.pager(OActivity.class, sql, pageNo, pageSize);
        if (isNotEmpty(pager)) {
            for (OActivity activity : pager.getResultList()) {
                activity.setUserActivityStatus(this.getActivityStatusDesc(userId, activity).getString("activityCode"));
                activity.setUserActivityStatusMsg(this.getActivityStatusDesc(userId, activity).getString("activityMsg"));
            }
        }
        return pager;
    }

    /**
     * 活动详情
     *
     * @param activityId
     * @return
     */
    public OActivity findValidActivity(long activityId) {
        if (activityId < 1) {
            return null;
        }
        OActivity a = findById(OActivity.class, activityId);
        if (a!=null && a.getStatus() == OActivity.STATUS_YES) {
            return a;
        }
        return null;
    }

    /**
     * 根据活动ID获取参加人员
     *
     * @param activityId
     * @param clubId
     * @return
     */
    public List<OActivityMember> listMember(long activityId, Integer status) {
        if (activityId <= 0) {
            return null;
        }
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql(" select id from ").appendSql(getTableName(OActivityMember.class)).appendSql(" where ");
        sql.appendSql(" activity_id = ").appendValue(activityId);
        if (status != null) {
            sql.appendSql(" and status = ").appendValue(status);
        }
        return loadUsers(list(OActivityMember.class, sql));
    }

    /**
     * 我参与的活动 userId：用户ID
     */
    public Pager<OActivity> pageActivity4Join(long userId, long oClubId, int pageNo, int pageSize) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql(" select activity.activity_id from ").appendSql(getTableName(OActivityMember.class)).appendSql(" member, ");
        sql.appendSql(getTableName(OActivity.class)).appendSql(" activity where  member.activity_id = activity.activity_id ");
        sql.appendSql(" and member.user_id = ").appendValue(userId);
        if (oClubId > 0) {
            sql.appendSql(" and activity.o_club_id = ").appendValue(oClubId);
        }
        sql.appendSql(" and activity.status =").appendValue(OActivity.STATUS_YES);
        return pagerService.pager(OActivity.class, sql, pageNo, pageSize);
    }

    /**
     * 我参与的活动 userId：用户ID
     */
    public List<OActivity> listActivity4Join(long userId, long oClubId) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql(" select activity.activity_id from ").appendSql(getTableName(OActivityMember.class)).appendSql(" member, ");
        sql.appendSql(getTableName(OActivity.class)).appendSql(" activity where  member.activity_id = activity.activity_id ");
        sql.appendSql(" and member.user_id = ").appendValue(userId);
        if (oClubId > 0) {
            sql.appendSql(" and activity.o_club_id = ").appendValue(oClubId);
        }
        sql.appendSql(" and activity.status =").appendValue(OActivity.STATUS_YES);
        return list(OActivity.class, sql);
    }

    /**
     * 获取热门活动（进行中的）
     *
     * @param userId
     * @param oClubId
     * @param limit
     * @return
     */
    public List<OActivity> listHotActivity(long userId, long oClubId, int limit) {
        return listActivityBy(userId, oClubId, limit, Boolean.FALSE, Boolean.TRUE);
    }

    /**
     * 活动列表 -->>>未结束的活动，按活动开始时间
     *
     * @param userId 用于判断用户的状态，为NULL时不做判断
     * @param oClubId 必要的参数
     * @param limit 拿前几，为NULL时不限制
     * @param isEnd 活动是否结束，为NULL时不限制
     * @param isValid 活动是否有效，为NULL时不限制
     * @return
     */
    private List<OActivity> listActivityBy(Long userId, long oClubId, Integer limit, Boolean isEnd, Boolean isValid) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql(" select activity_id from ").appendSql(getTableName(OActivity.class)).appendSql(" where 1=1 ");
        if (isEnd != null) {
            if (!isEnd) {//未结束
                sql.appendSql(" and end_date >= ").appendValue(DateUtils.getNow());
            } else {//结束
                sql.appendSql(" and end_date < ").appendValue(DateUtils.getNow());
            }
        }
        sql.appendSql(" and o_club_id = ").appendValue(oClubId);
        if (isValid != null) {
            sql.appendSql(" and status =").appendValue(isValid ? OActivity.STATUS_YES : OActivity.STATUS_NO);
        }
        sql.appendSql(" order by create_at desc ");
        List<OActivity> list;
        if (limit != null) {
            list = listLimit(OActivity.class, sql, limit);
        } else {
            list = list(OActivity.class);
        }
        for (OActivity activity : list) {
            activity.setUserActivityStatus(this.getActivityStatusDesc(userId, activity).getString("activityCode"));
            activity.setUserActivityStatusMsg(this.getActivityStatusDesc(userId, activity).getString("activityMsg"));
        }
        return list;
    }

    /**
     * 拿出该会员报名该活动的信息
     *
     * @param activityId
     * @param userId
     * @return
     */
    public OActivityMember findActivityMember(long activityId, long userId) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql(" select * from ").appendSql(getTableName(OActivityMember.class)).appendSql(" where activity_id = ").appendValue(activityId);
        sql.appendSql(" and user_id = ").appendValue(userId);
        return findFirst(OActivityMember.class, sql);
    }

    /**
     * 取消报名（物理删除）
     *
     * @param activityId
     * @param userId
     */
    public int deleteActivityMember(long activityId, long userId) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql(" delete from ").appendSql(getTableName(OActivityMember.class));
        sql.appendSql(" where activity_id = ").appendValue(activityId).appendSql(" and user_id =").appendValue(userId);
        return update(sql);
    }

    /**
     * 用户退出车友会或者移除车友会时（物理）删除报名记录
     *
     *
     *
     * @param userId
     * @param status
     * @return
     */
    public int removeActivityMemberBy(long userId, long oClubId) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql("delete from ").appendSql(getTableName(OActivityMember.class));
        sql.appendSql(" where user_id=").appendValue(userId);
        sql.appendSql(" and activity_id in (select a.activity_id from ").appendSql(getTableName(OActivity.class)).appendSql(" a,").appendSql(getTableName(OClub.class)).appendSql(" b where a.o_club_id=b.o_club_id and b.o_club_id=").appendValue(oClubId).appendSql(")");
        return update(sql);
    }

    /**
     * 用户退出车友会或者移除车友会时（逻辑）删除创建的活动
     *
     * @param userId
     * @param status
     * @return
     */
    public int removeActivityBy(long userId, long oClubId) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql("update ").appendSql(getTableName(OActivity.class));
        sql.appendSql(" set status=").appendValue(OActivity.STATUS_NO);
        sql.appendSql(" where create_by=").appendValue(userId);
        sql.appendSql(" and o_club_id = ").appendValue(oClubId);
        return update(sql);
    }

    /**
     * 活动报名
     *
     * @param activityMember
     */
    public long createActityMember(OActivityMember activityMember) {
        return geliDao.create(activityMember);
    }

    /**
     *
     * 更新活动参加人员总数
     *
     * @param activityId
     */
    public void updateActivityJoinNum(long activityId) {
        int total = countActivityMember(activityId, OActivityMember.STATUS_PASS);
        OActivity activity = findById(OActivity.class, activityId);
        if (activity.getJoinNum() != total) {
            activity.setJoinNum(total);
            geliDao.update(activity, "join_num");
        }
    }

    /**
     * 逻辑删除活动
     *
     * @param activityId
     * @return
     */
    public boolean removeActivity(OActivity activity) {
        if(activity == null) return false;
        activity.setStatus(OActivity.STATUS_NO);
        return geliDao.update(activity, "status") > 0;
    }

    /**
     * 取出车友会最新的前N条活动（未结束的）
     *
     * @param oClubId
     * @param num
     * @return
     */
    public List<OActivity> getLatestActivity(long oClubId, int num) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql(" select activity_id from ").appendSql(getTableName(OActivity.class));
        sql.appendSql(" where o_club_id =").appendValue(oClubId);
        sql.appendSql(" and status =").appendValue(OActivity.STATUS_YES);
        sql.appendSql(" and end_date >=").appendValue(DateUtils.getNow());
        sql.appendSql(" order by create_at desc ");
        return listLimit(OActivity.class, sql, num);
    }

    /**
     * 最新的一条（未结束的）活动
     *
     * @param oClubId
     * @return
     */
    public OActivity getLatestActivity(long oClubId) {
        List<OActivity> list = getLatestActivity(oClubId, 1);
        if (list != null && !list.isEmpty()) {
            return list.get(0);
        }
        return null;
    }

    /**
     * 根据车友会ID统计活动数量
     *
     * @param oClubId
     * @return
     */
    public int countActivity(long oClubId) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql(" select count(1) from ").appendSql(getTableName(OActivity.class));
        sql.appendSql(" where o_club_id = ").appendValue(oClubId);
        sql.appendSql(" and status = ").appendValue(OActivity.STATUS_YES);
        return count(sql);
    }

    /**
     * 根据id数组查询活动
     *
     * @param ids
     * @return
     */
    public List<OActivity> listActivity(Object[] ids) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql(" select activity_id from ").appendSql(getTableName(OActivity.class));
        sql.appendSql(" where activity_id in ").appendValues(ids);
        sql.appendSql(" and status = ").appendValue(OActivity.STATUS_YES);
        sql.appendSql(" order by begin_date desc ");
        return list(OActivity.class, sql);
    }

    /**
     * 根据活动ID和用户ID获取报名信息
     *
     * @param userId
     * @param activityId
     * @param status 充许为NULL
     * @return
     */
    public OActivityMember getApplyInfo(long userId, long activityId, Integer status) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql(" select * from ").appendSql(getTableName(OActivityMember.class));
        sql.appendSql(" where user_id = ").appendValue(userId);
        sql.appendSql(" and activity_id = ").appendValue(activityId);
        if (status != null) {
            sql.appendSql(" and status = ").appendValue(status);
        }
        return findFirst(OActivityMember.class, sql);
    }

    /**
     * 拒绝报名（物理删除）
     *
     * @param member
     */
    public void rejectApply(OActivityMember member) {
        geliDao.delete(member, member.getId());
        updateActivityJoinNum(member.getActivityId());
    }

    /**
     * 通过报名
     *
     * @param member
     */
    public void passApply(OActivityMember member) {
        member.setStatus(OActivityMember.STATUS_PASS);
        geliDao.update(member, "status");
        updateActivityJoinNum(member.getActivityId());
    }

    /**
     * 列出待审的人员
     *
     * @param activityId
     * @return
     */
    public List<OActivityMember> listActivityMember4Audit(long activityId) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql("select id from ").appendSql(getTableName(OActivityMember.class)).appendSql(" where activity_id=").appendValue(activityId).appendSql(" and status=").appendValue(OActivityMember.STATUS_APPLY);
        return list(OActivityMember.class, sql);
    }

    /**
     * 根据会员ID和活动ID判断状态显示
     *
     * @param userId
     * @param activity
     * @return
     */
    public Result getActivityStatusDesc(long userId, OActivity activity) {
        if (activity == null) {
            return new Result().set("activityMsg", "该活动不存在").set("activityCode", "100");
        }
        OActivityMember aMember = null;
        if (userId > 0) {
            aMember = this.getApplyInfo(userId, activity.getActivityId(), null);
        }
        long nowDate = DateUtils.getNow().getTime();
        if (nowDate >= activity.getEndDate().getTime()) {
            return new Result().set("activityMsg", "活动已结束").set("activityCode", "105");
        }
        if (activity.getBeginDate().getTime() > activity.getSignupDate().getTime()
                && nowDate > activity.getBeginDate().getTime()) {
            return new Result().set("activityMsg", "活动进行中").set("activityCode", "104");
        }
        if (nowDate > activity.getSignupDate().getTime()) {
            return new Result().set("activityMsg", "报名已结束").set("activityCode", "103");
        }
        if (aMember != null && aMember.getStatus() == OActivityMember.STATUS_PASS) {
            return new Result().set("activityMsg", "已报名").set("activityCode", "203");
        }
        if (activity.getMaxJoin() > 0 && activity.getJoinNum() >= activity.getMaxJoin()) {
            //人数已满
            return new Result().set("activityMsg", "报名已结束").set("activityCode", "102");
        }
        if (aMember != null && aMember.getStatus() == OActivityMember.STATUS_APPLY) {
            return new Result().set("activityMsg", "审核中").set("activityCode", "201");
        }
        return new Result().set("activityMsg", "火热报名中").set("activityCode", "101");
    }

    /**
     * 统计报名总人数
     *
     * @param activityId
     * @param status
     * @return
     */
    public int countActivityMember(long activityId, int status) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql("select sum(join_num) from ").appendSql(getTableName(OActivityMember.class)).appendSql(" where activity_id = ").appendValue(activityId).appendSql(" and status=").appendValue(status);
        return count(sql);
    }

    /**
     * 分布查询车友会活动
     *
     * @param oClubId
     * @param pageNo
     * @param pageSize
     * @return
     */
    public Pager<Activity> pagerActivityByClub(long oClubId, int pageNo, int pageSize) {
        SqlBuilder sql = new SqlBuilder();
        sql.appendSql("select a.activity_id from ").appendSql(getTableName(Activity.class)).appendSql(" a,").appendSql(getTableName(OClubMember.class)).appendSql(" m where a.club_id=m.club_id and a.status=").appendValue(Activity.STATUS_YES);
        sql.appendSql(" and m.o_club_id=").appendValue(oClubId).appendSql(" order by a.begin_date desc");
        Pager<Activity> pager = pagerService.pager(Activity.class, sql, pageNo, pageSize);
        clubService.loadTransientClubs(pager.getResultList());
        return pager;
    }
}
